package mergesort;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.RecursiveTask;

public class ArraySortTask extends RecursiveTask<int[]> {

	private static final long serialVersionUID = 1L;
	int[] dividedArrray;

	  public ArraySortTask(int[] dividedArray) {
	    this.dividedArrray = dividedArray;
	  }

	  @Override
	  protected int[] compute() {
	    if (dividedArrray.length > 1) {
	      
	      List<int[]> separatedArray = separationArray();
	      
	      ArraySortTask task1 = new ArraySortTask(separatedArray.get(0));
	      ArraySortTask task2 = new ArraySortTask(separatedArray.get(1));
	      invokeAll(task1, task2);
	      
	      int[] array1 = task1.join();
	      int[] array2 = task2.join();
	      
	      int[] mergedArray = new int[array1.length + array2.length];
	      
	      mergeArrays(task1.join(), task2.join(), mergedArray);

	      return mergedArray;
	    }
	    return dividedArrray;
	  }
	  
	  // Return List where in [0] pos is left side of array and in [1] pos is right side
	  private List<int[]> separationArray(){
	    
	    int [] left = Arrays.copyOfRange(dividedArrray, 0,
	              dividedArrray.length / 2);
	      
	    int [] right = Arrays.copyOfRange(dividedArrray,
	              dividedArrray.length / 2,
	              dividedArrray.length);
	    return Arrays.asList(left,right);
	    
	  }
	  //Merge 2 arrays to one
	  private void mergeArrays(
	          int[] array1, 
	          int[] array2, 
	          int[] mergedArray) {
	    
	    int i = 0, j = 0, k = 0;
	    
	    while ((i < array1.length) && (j < array2.length)) {
	    
	      if (array1[i] < array2[j]) {
	        mergedArray[k] = array1[i++];
	      } else {
	        mergedArray[k] = array2[j++];
	      }
	      
	      k++;
	    }
	    
	    if (i == array1.length) {
	      
	      for (int a = j; a < array2.length; a++) {
	        mergedArray[k++] = array2[a];
	      }
	      
	    } else {
	      
	      for (int a = i; a < array1.length; a++) {
	        mergedArray[k++] = array1[a];
	      }
	      
	    }
	  }
	}